package com.yupi.springbootinit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.springbootinit.common.DeleteRequest;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.exception.ThrowUtils;
import com.yupi.springbootinit.mapper.*;
import com.yupi.springbootinit.model.dto.qa.QaInspectionReportAddRequest;
import com.yupi.springbootinit.model.dto.qa.QaInspectionReportQueryRequest;
import com.yupi.springbootinit.model.dto.qa.QaInspectionReportUpdateRequest;
import com.yupi.springbootinit.model.entity.*;
import com.yupi.springbootinit.model.vo.qa.QaInspectionReportDetailVO;
import com.yupi.springbootinit.model.vo.qa.QaInspectionReportProductVO;
import com.yupi.springbootinit.service.*;
import com.yupi.springbootinit.service.SalesOrderService;
import com.yupi.springbootinit.utils.excel.QaInspectionReportExcelExporter;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
* @author Administrator
* @description 针对表【qaInspectionReport(成品检验报告（表头）)】的数据库操作Service实现
* @createDate 2024-02-25 17:04:02
*/
@Slf4j
@Service
public class QaInspectionReportServiceImpl extends ServiceImpl<QaInspectionReportMapper, QaInspectionReport>
        implements QaInspectionReportService {

    @Resource
    private QaInspectionReportDimService qaInspectionReportDimService;
    @Resource
    private QaInspectionInstrumentService qaInspectionInstrumentService;
    @Resource
    private AttachmentService attachmentService;
    @Resource
    private ProcessSheetService processSheetService;
    @Resource
    private ProcessSheetProductMapper processSheetProductMapper;
    @Resource
    private ProcessSheetBatchProductMapper processSheetBatchProductMapper;
    @Resource
    private QaInspectionReportSeqService qaInspectionReportSeqService;
    @Resource
    private WorkflowTaskService workflowTaskService;
    @Resource
    private DepartmentMapper departmentMapper;
    @Resource
    private WorkflowTaskMapper workflowTaskMapper;
    @Resource
    private QaInspectionAppearanceService qaInspectionAppearanceService;
    @Resource
    private ProcessBatchStepMapper processBatchStepMapper;
    @Resource
    private ProcessBatchMapper processBatchMapper;
    @Resource
    private SalesOrderService salesOrderService;
    @Resource
    private ProcessSheetMapper processSheetMapper;

    @Override
    public long addQaInspectionReport(QaInspectionReportAddRequest qaInspectionReportAddRequest) {
        QaInspectionReport qaInspectionReport = new QaInspectionReport();
        BeanUtils.copyProperties(qaInspectionReportAddRequest, qaInspectionReport);
        // 唯一性：一个工艺单仅允许生成一个检验报告
        if (qaInspectionReport.getProcessSheetId() != null) {
            long cnt = this.lambdaQuery()
                    .eq(QaInspectionReport::getProcessSheetId, qaInspectionReport.getProcessSheetId())
                    .eq(QaInspectionReport::getIsDelete, 0)
                    .count();
            ThrowUtils.throwIf(cnt > 0, ErrorCode.OPERATION_ERROR, "该工艺单已生成检验报告，禁止重复创建");
        }
        this.save(qaInspectionReport);
        return qaInspectionReport.getId();
    }

    @Override
    public boolean deleteQaInspectionReport(DeleteRequest deleteRequest) {
        return this.removeById(deleteRequest.getId());
    }

    @Override
    public boolean updateQaInspectionReport(QaInspectionReportUpdateRequest qaInspectionReportUpdateRequest, User currentUser) {
        if (qaInspectionReportUpdateRequest == null || qaInspectionReportUpdateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "更新参数不能为空");
        }

        Long reportId = qaInspectionReportUpdateRequest.getId();

        // 1. 查询报告
        QaInspectionReport existingReport = this.getById(reportId);
        if (existingReport == null || existingReport.getIsDelete() == 1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "检验报告不存在");
        }

        // 2. 权限校验
        if (!checkCanEdit(existingReport, currentUser)) {
            String msg = "SUBMITTED".equals(existingReport.getStatus())
                    ? "报告已提交，只有管理员可以修改"
                    : "您没有权限修改此报告";
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, msg);
        }

        // 3. 执行更新
        QaInspectionReport qaInspectionReport = new QaInspectionReport();
        BeanUtils.copyProperties(qaInspectionReportUpdateRequest, qaInspectionReport);
        qaInspectionReport.setUpdateTime(LocalDateTime.now());

        boolean updated = this.updateById(qaInspectionReport);

        if (updated) {
            log.info("检验报告更新成功: reportId={}, operator={}", reportId, currentUser.getUserName());
        }

        return updated;
    }

    @Override
    public QaInspectionReport getQaInspectionReportById(long id) {
        return this.getById(id);
    }

    @Override
    public List<QaInspectionReport> listQaInspectionReport(QaInspectionReportQueryRequest qaInspectionReportQueryRequest) {
        QueryWrapper<QaInspectionReport> queryWrapper = getQueryWrapper(qaInspectionReportQueryRequest);
        return this.list(queryWrapper);
    }

    @Override
    public Page<QaInspectionReport> listQaInspectionReportByPage(QaInspectionReportQueryRequest qaInspectionReportQueryRequest) {
        long current = qaInspectionReportQueryRequest.getCurrent();
        long size = qaInspectionReportQueryRequest.getPageSize();
        Page<QaInspectionReport> page = new Page<>(current, size);
        QueryWrapper<QaInspectionReport> queryWrapper = getQueryWrapper(qaInspectionReportQueryRequest);
        return this.page(page, queryWrapper);
    }

    private QueryWrapper<QaInspectionReport> getQueryWrapper(QaInspectionReportQueryRequest qaInspectionReportQueryRequest) {
        QueryWrapper<QaInspectionReport> queryWrapper = new QueryWrapper<>();
        if (qaInspectionReportQueryRequest == null) {
            return queryWrapper;
        }
        Long id = qaInspectionReportQueryRequest.getId();
        if (id != null && id > 0) {
            queryWrapper.eq("id", id);
        }
        return queryWrapper;
    }

    /**
     * 获取检验报告详情（包含主尺寸和仪器设备）
     *
     * @param reportId    报告ID
     * @param currentUser 当前登录用户（用于权限判断）
     * @return 报告详情VO
     */
    /**
     * 获取检验报告详情（包含产品列表、主尺寸和仪器设备）
     *
     * @param reportId    报告ID
     * @param currentUser 当前登录用户（用于权限判断）
     * @return 报告详情VO
     */
    @Override
    public QaInspectionReportDetailVO getReportDetail(Long reportId, User currentUser) {
        if (reportId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "报告ID不能为空");
        }

        // 1. 查询报告主表
        QaInspectionReport report = this.getById(reportId);
        if (report == null || report.getIsDelete() == 1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "检验报告不存在");
        }

        // 2. 组装 VO
        QaInspectionReportDetailVO vo = new QaInspectionReportDetailVO();
        BeanUtils.copyProperties(report, vo);

        // 3. 查询产品列表
        List<QaInspectionReportProductVO> products = queryProductList(report);
        vo.setProducts(products);

        // 计算总数量
        int totalQuantity = products.stream()
                .mapToInt(p -> p.getProductionQuantity() != null ? p.getProductionQuantity() : 0)
                .sum();
        vo.setTotalQuantity(totalQuantity);

        // 兼容旧版本字段（取第一个产品或主产品信息）
        if (products != null && !products.isEmpty()) {
            QaInspectionReportProductVO firstProduct = products.get(0);
            vo.setProductName(firstProduct.getProductName());
            vo.setSpecModel(firstProduct.getSpecification());
        }
        vo.setQuantity(totalQuantity);

        // 4. 查询主尺寸列表（FAI1~FAI10）
        List<QaInspectionReportDim> dimensions = qaInspectionReportDimService.lambdaQuery()
                .eq(QaInspectionReportDim::getReportId, reportId)
                .orderByAsc(QaInspectionReportDim::getOrderNo)
                .list();
        vo.setDimensions(dimensions);

        // 5. 查询仪器设备列表
        List<QaInspectionInstrument> instruments = qaInspectionInstrumentService.lambdaQuery()
                .eq(QaInspectionInstrument::getReportId, reportId)
                .orderByAsc(QaInspectionInstrument::getCreateTime)
                .list();
        vo.setInstruments(instruments);

        // 6. 判断当前用户是否可编辑
        boolean canEdit = checkCanEdit(report, currentUser);
        vo.setCanEdit(canEdit);

        log.info("获取检验报告详情成功: reportId={}, status={}, canEdit={}, productCount={}",
                reportId, report.getStatus(), canEdit, products.size());

        return vo;
    }

    /**
     * 查询产品列表
     *
     * 逻辑：
     * 1. 如果有 batchId（版次ID），从 process_sheet_batch_product 查询
     * 2. 如果只有 processSheetId，从 process_sheet_product 查询
     * 3. 如果都没有，返回报告主表中的产品信息（兼容旧数据）
     *
     * @param report 检验报告
     * @return 产品列表
     */
    private List<QaInspectionReportProductVO> queryProductList(QaInspectionReport report) {
        List<QaInspectionReportProductVO> products = new ArrayList<>();

        // 情况1：有版次ID，从版次产品明细表查询
        if (report.getBatchId() != null) {
            // 先查询 process_batch 获取 batch_plan_id
            ProcessBatch batch = processBatchMapper.selectById(report.getBatchId());
            if (batch != null && batch.getBatchPlanId() != null) {
                // 从版次产品明细表查询
                List<ProcessSheetBatchProduct> batchProducts = processSheetBatchProductMapper.selectList(
                        new QueryWrapper<ProcessSheetBatchProduct>()
                                .eq("batch_id", batch.getBatchPlanId())
                                .eq("is_deleted", 0)
                                .orderByAsc("id")
                );

                if (batchProducts != null && !batchProducts.isEmpty()) {
                    for (ProcessSheetBatchProduct bp : batchProducts) {
                        QaInspectionReportProductVO productVO = new QaInspectionReportProductVO();
                        productVO.setProductCode(bp.getProductCode());
                        productVO.setProductName(bp.getProductName());
                        productVO.setProductionQuantity(bp.getProductionQuantity());

                        // 查询工艺单产品表获取更多信息（规格、高度、重量）
                        if (bp.getProductId() != null) {
                            ProcessSheetProduct sheetProduct = processSheetProductMapper.selectById(bp.getProductId());
                            if (sheetProduct != null) {
                                productVO.setSpecification(sheetProduct.getSpecification());
                                productVO.setProductHeight(sheetProduct.getProductHeight());
                                productVO.setUnitWeight(sheetProduct.getUnitWeight());
                            }
                        }

                        products.add(productVO);
                    }
                    return products;
                }
            }
        }

        // 情况2：从工艺单产品明细表查询
        if (report.getProcessSheetId() != null) {
            List<ProcessSheetProduct> sheetProducts = processSheetProductMapper.selectList(
                    new QueryWrapper<ProcessSheetProduct>()
                            .eq("process_sheet_id", report.getProcessSheetId())
                            .eq("is_deleted", 0)
                            .orderByAsc("sort_order", "id")
            );

            if (sheetProducts != null && !sheetProducts.isEmpty()) {
                for (ProcessSheetProduct sp : sheetProducts) {
                    QaInspectionReportProductVO productVO = new QaInspectionReportProductVO();
                    productVO.setProductCode(sp.getProductCode());
                    productVO.setProductName(sp.getProductName());
                    productVO.setSpecification(sp.getSpecification());
                    productVO.setProductHeight(sp.getProductHeight());
                    productVO.setUnitWeight(sp.getUnitWeight());
                    productVO.setProductionQuantity(sp.getQuantity());
                    products.add(productVO);
                }
                return products;
            }
        }

        // 情况3：兼容旧数据，使用报告主表中的产品信息
        if (StringUtils.isNotBlank(report.getProductName())) {
            QaInspectionReportProductVO productVO = new QaInspectionReportProductVO();
            productVO.setProductName(report.getProductName());
            productVO.setSpecification(report.getSpecModel());
            productVO.setProductionQuantity(report.getQuantity());
            products.add(productVO);
        }

        return products;
    }

    /**
     * 判断当前用户是否可编辑报告
     *
     * @param report      报告实体
     * @param currentUser 当前用户
     * @return true-可编辑, false-不可编辑
     */
    private boolean checkCanEdit(QaInspectionReport report, User currentUser) {
        if (currentUser == null) {
            return false;
        }

        // 1. 如果是草稿状态，品质部人员可编辑
        if ("DRAFT".equals(report.getStatus())) {
            // 检查用户是否属于品质部（部门编码 PZ001）
            if (currentUser.getDepartmentId() != null) {
                Department dept = departmentMapper.selectById(currentUser.getDepartmentId());
                return dept != null && "PZ001".equals(dept.getDepartmentCode());
            }
            return false;
        }

        // 2. 如果是已提交状态，只有管理员可编辑
        if ("SUBMITTED".equals(report.getStatus())) {
            return "admin".equals(currentUser.getUserRole());
        }

        // 3. 其他状态不可编辑
        return false;
    }


    /**
     * 提交检验报告
     *
     * @param reportId 报告ID
     * @param userId   提交人ID
     * @param userName 提交人姓名
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitReport(Long reportId, Long userId, String userName) {
        if (reportId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "报告ID不能为空");
        }

        log.info("开始提交检验报告: reportId={}, userId={}, userName={}", reportId, userId, userName);

        // 1. 查询报告
        QaInspectionReport report = this.getById(reportId);
        if (report == null || report.getIsDelete() == 1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "检验报告不存在");
        }

        // 2. 检查报告状态（只有草稿状态可以提交）
        if (!"DRAFT".equals(report.getStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR,
                    "报告当前状态不允许提交（状态：" + report.getStatus() + "）");
        }

        // 3. 校验必填信息
        validateRequiredFields(reportId, report);

        // 4. 自动填充 note（如果判定为合格且 note 为空）
        if ("PASS".equals(report.getFinalJudgement()) && StringUtils.isBlank(report.getNote())) {
            report.setNote("产品符合，判断合格");
        }

        // 5. 更新报告状态
        report.setStatus("SUBMITTED");
        report.setInspectorId(userId);
        report.setInspectorName(userName);
        report.setInspectedAt(LocalDateTime.now());
        report.setUpdateTime(LocalDateTime.now());

        boolean updated = this.updateById(report);
        if (!updated) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交报告失败");
        }

        log.info("检验报告状态更新成功: reportId={}, status=SUBMITTED", reportId);

        // 6. 完成关联的任务
        if (report.getTaskId() != null) {
            try {
                // 查询任务
                WorkflowTask task = workflowTaskMapper.selectById(report.getTaskId());
                if (task != null && !"DONE".equals(task.getTaskStatus())) {
                    // 先尝试认领（如果未认领）
                    if (task.getClaimedBy() == null) {
                        log.info("任务未认领，尝试自动认领: taskId={}", task.getId());
                        workflowTaskService.claimTask(task.getId(), userId, userName, null);
                    }

                    // 完成任务
                    boolean taskCompleted = workflowTaskService.completeTask(
                            task.getId(),
                            userId,
                            userName,
                            "检验报告已提交，报告编号：" + report.getReportNo()
                    );

                    if (taskCompleted) {
                        log.info("✅ 关联任务已完成: taskId={}, reportId={}", task.getId(), reportId);
                    } else {
                        log.warn("⚠️ 完成任务失败: taskId={}, reportId={}", task.getId(), reportId);
                    }
                } else if (task != null) {
                    log.info("任务已是完成状态，跳过: taskId={}, status={}", task.getId(), task.getTaskStatus());
                }
            } catch (Exception e) {
                log.error("❌ 完成关联任务失败: taskId={}, reportId={}", report.getTaskId(), reportId, e);
                // 不影响主流程，任务可以手动完成
            }
        } else {
            log.warn("报告未关联任务: reportId={}", reportId);
        }

        log.info("✅ 检验报告提交成功: reportId={}, reportNo={}, submitter={}",
                reportId, report.getReportNo(), userName);

        // ✅ 订单状态推进：检验报告提交 → COMPLETED
        try {
            if (report.getProcessSheetId() != null) {
                ProcessSheet sheet = processSheetMapper.selectById(report.getProcessSheetId());
                if (sheet != null && sheet.getSourceId() != null) {
                    Long orderId = sheet.getSourceId();
                    salesOrderService.updateOrderStatus(orderId, "COMPLETED", "订单已完成", 100.0);
                    log.info("✅ 订单状态更新为COMPLETED: orderId={}, processSheetId={}", orderId, report.getProcessSheetId());
                } else {
                    log.warn("⚠️ 未找到工艺单或来源订单ID为空，无法更新为COMPLETED: processSheetId={}", report.getProcessSheetId());
                }
            } else {
                log.warn("⚠️ 报告未关联工艺单，无法更新订单为COMPLETED: reportId={}", reportId);
            }
        } catch (Exception e) {
            log.warn("⚠️ 更新订单状态为COMPLETED失败（不影响报告提交）: reportId={}, err={}", reportId, e.getMessage());
        }

        return true;
    }

    /**
     * 校验必填字段
     *
     * @param reportId 报告ID
     * @param report   报告实体
     */
    private void validateRequiredFields(Long reportId, QaInspectionReport report) {
        log.info("开始校验必填字段: reportId={}", reportId);

        // 1. 生产日期/批次号
        if (StringUtils.isBlank(report.getLotNo())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "生产日期/批次号不能为空");
        }

        // 2. 主尺寸（FAI1~FAI10）
        List<QaInspectionReportDim> dims = qaInspectionReportDimService.lambdaQuery()
                .eq(QaInspectionReportDim::getReportId, reportId)
                .orderByAsc(QaInspectionReportDim::getOrderNo)
                .list();

        if (dims == null || dims.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "主尺寸数据不存在");
        }

        for (QaInspectionReportDim dim : dims) {
            // 跳过空的尺寸项（要求和实测值都为空时视为未使用）
            boolean isEmpty = StringUtils.isBlank(dim.getRequirement()) && StringUtils.isBlank(dim.getMeasuredValue());
            if (isEmpty) {
                continue;
            }

            // 如果填写了其中一个，则两个都必须填写
            if (StringUtils.isBlank(dim.getRequirement())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR,
                        dim.getItemNo() + " 的要求不能为空（已填写实测值）");
            }
            if (StringUtils.isBlank(dim.getMeasuredValue())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR,
                        dim.getItemNo() + " 的实测值不能为空（已填写要求）");
            }
        }

        log.info("主尺寸校验通过: reportId={}, 总数={}, 有效数={}", reportId, dims.size(), 
                dims.stream().filter(d -> StringUtils.isNotBlank(d.getRequirement()) || StringUtils.isNotBlank(d.getMeasuredValue())).count());

        // 3. 尺寸检测结论
        if (StringUtils.isBlank(report.getDimensionConclusion())
                || "PENDING".equals(report.getDimensionConclusion())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "尺寸检测结论不能为空，请选择合格/不合格/N/A");
        }

        if (!"PASS".equals(report.getDimensionConclusion())
                && !"FAIL".equals(report.getDimensionConclusion())
                && !"NA".equals(report.getDimensionConclusion())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,
                    "尺寸检测结论只能是 PASS（合格）、FAIL（不合格）或 NA");
        }

        log.info("尺寸检测结论校验通过: reportId={}, dimensionConclusion={}", reportId, report.getDimensionConclusion());

        // 4. 外观检测结论
        if (StringUtils.isBlank(report.getAppearanceConclusion())
                || "PENDING".equals(report.getAppearanceConclusion())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "外观检测结论不能为空，请选择合格/不合格/N/A");
        }

        if (!"PASS".equals(report.getAppearanceConclusion())
                && !"FAIL".equals(report.getAppearanceConclusion())
                && !"NA".equals(report.getAppearanceConclusion())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,
                    "外观检测结论只能是 PASS（合格）、FAIL（不合格）或 NA");
        }

        log.info("外观检测结论校验通过: reportId={}, appearanceConclusion={}", reportId, report.getAppearanceConclusion());

        // 5. 仪器设备（至少1个）
        List<QaInspectionInstrument> instruments = qaInspectionInstrumentService.lambdaQuery()
                .eq(QaInspectionInstrument::getReportId, reportId)
                .list();

        if (instruments == null || instruments.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "至少需要添加1个仪器设备");
        }

        // 校验每个仪器的必填字段
        for (int i = 0; i < instruments.size(); i++) {
            QaInspectionInstrument inst = instruments.get(i);
            String prefix = "仪器" + (i + 1);

            if (StringUtils.isBlank(inst.getInstrumentName())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, prefix + " 的名称不能为空");
            }
            if (StringUtils.isBlank(inst.getInstrumentCode())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, prefix + " 的编号不能为空");
            }
            if (inst.getValidUntil() == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, prefix + " 的有效期不能为空");
            }
        }

        log.info("仪器设备校验通过: reportId={}, 数量={}", reportId, instruments.size());

        // 6. 判定结果
        if (StringUtils.isBlank(report.getFinalJudgement())
                || "PENDING".equals(report.getFinalJudgement())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "判定结果不能为空，请选择合格或不合格");
        }

        if (!"PASS".equals(report.getFinalJudgement())
                && !"FAIL".equals(report.getFinalJudgement())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,
                    "判定结果只能是 PASS（合格）或 FAIL（不合格）");
        }

        log.info("✅ 所有必填字段校验通过: reportId={}", reportId);
    }


    @Override
    public byte[] exportReportExcel(Long reportId) {
        log.info("========== 开始导出检验报告Excel ==========");
        log.info("reportId={}", reportId);

        QaInspectionReport report = this.getById(reportId);
        if (report == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "检验报告不存在");
        }

        // 补齐产品信息
        if (StringUtils.isBlank(report.getProductName()) || StringUtils.isBlank(report.getSpecModel())) {
            if (report.getProcessSheetId() != null) {
                ProcessSheet sheet = processSheetService.getById(report.getProcessSheetId());
                if (sheet != null) {
                    if (StringUtils.isBlank(report.getProductName())) {
                        report.setProductName(sheet.getProductName());
                    }
                    if (StringUtils.isBlank(report.getSpecModel())) {
                        report.setSpecModel(sheet.getSpecification());
                    }
                    if (report.getQuantity() == null) {
                        report.setQuantity(sheet.getQuantity());
                    }
                }
            }
        }

        // 检验日期与报告编号
        Date now = new Date();
        if (report.getReportDate() == null) {
            report.setReportDate(now);
        }
        if (StringUtils.isBlank(report.getReportNo())) {
            String dateKey = new SimpleDateFormat("yyyyMMdd").format(now);
            QaInspectionReportSeq seq = qaInspectionReportSeqService.getById(dateKey);
            int nextVal = 1;
            if (seq == null) {
                seq = new QaInspectionReportSeq();
                seq.setDateKey(dateKey);
                seq.setNextVal(1);
                qaInspectionReportSeqService.save(seq);
            } else {
                nextVal = seq.getNextVal() + 1;
                seq.setNextVal(nextVal);
                qaInspectionReportSeqService.updateById(seq);
            }
            String reportNo = dateKey + String.format("%02d", seq.getNextVal());
            report.setReportNo(reportNo);
            this.updateById(report);
        }

        // 查询主尺寸
        List<QaInspectionReportDim> dims = qaInspectionReportDimService.lambdaQuery()
                .eq(QaInspectionReportDim::getReportId, reportId)
                .orderByAsc(QaInspectionReportDim::getOrderNo)
                .list();
        Map<String, QaInspectionReportDim> dimMap = new HashMap<>();
        if (dims != null) {
            for (QaInspectionReportDim d : dims) {
                dimMap.put(StringUtils.defaultIfBlank(d.getItemNo(), ""), d);
            }
        }

        // 查询仪器信息
        List<QaInspectionInstrument> instruments = qaInspectionInstrumentService.lambdaQuery()
                .eq(QaInspectionInstrument::getReportId, reportId)
                .orderByAsc(QaInspectionInstrument::getCreateTime)
                .last("limit 6")
                .list();

        // 读取Logo图片
        byte[] logoBytes = null;
        List<Attachment> logos = attachmentService.getAttachmentsByBizAndCategory("QA_INSP_REPORT", reportId, "LOGO");
        if (logos != null && !logos.isEmpty()) {
            logoBytes = QaInspectionReportExcelExporter.readFileBytes(logos.get(0).getFilePath());
        }
        if (logoBytes == null) {
            logoBytes = QaInspectionReportExcelExporter.readClasspathBytes("assets/company-logo.png");
        }

        // 读取产品图片
        byte[] imageBytes = null;
        List<Attachment> pics = attachmentService.getAttachmentsByBizAndCategory("QA_INSP_REPORT", reportId, "IMAGE");
        if (pics != null && !pics.isEmpty()) {
            imageBytes = QaInspectionReportExcelExporter.readFileBytes(pics.get(0).getFilePath());
        }

        // 调用工具类生成Excel
        return QaInspectionReportExcelExporter.exportToExcel(report, dimMap, instruments, logoBytes, imageBytes);
    }


    private void createMergedCell(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol, String text, CellStyle style) {
        sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
        Row row = getOrCreateRow(sheet, firstRow);
        Cell cell = getOrCreateCell(row, firstCol);
        cell.setCellValue(text);
        cell.setCellStyle(style);
        for (int r = firstRow; r <= lastRow; r++) {
            Row rr = getOrCreateRow(sheet, r);
            for (int c = firstCol; c <= lastCol; c++) {
                Cell cc = getOrCreateCell(rr, c);
                cc.setCellStyle(style);
            }
        }
    }

    private void createLabelValueRow(Sheet sheet, int rowIdx, int startCol, String label, String value, CellStyle style) {
        Row row = getOrCreateRow(sheet, rowIdx);
        Cell c1 = getOrCreateCell(row, startCol);
        c1.setCellValue(label);
        c1.setCellStyle(style);
        Cell c2 = getOrCreateCell(row, startCol+1);
        c2.setCellValue(org.apache.commons.lang3.StringUtils.defaultString(value));
        c2.setCellStyle(style);
        Cell c3 = getOrCreateCell(row, startCol+2);
        c3.setCellStyle(style);
        Cell c4 = getOrCreateCell(row, startCol+3);
        c4.setCellStyle(style);
        sheet.addMergedRegion(new CellRangeAddress(rowIdx, rowIdx, startCol+1, startCol+3));
    }

    private void createFAITable(Sheet sheet, int startRow, int startCol, CellStyle style, Map<String, QaInspectionReportDim> dimMap) {
        Row head = getOrCreateRow(sheet, startRow);
        String[] headers = {"尺寸", "要求", "实测", "结论"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = getOrCreateCell(head, startCol + i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(style);
        }
        for (int i = 1; i <= 10; i++) {
            Row r = getOrCreateRow(sheet, startRow + i);
            String key = "FAI" + i;
            QaInspectionReportDim dim = dimMap.getOrDefault(key, null);
            String dimName = key;
            String req = dim != null ? org.apache.commons.lang3.StringUtils.defaultString(dim.getRequirement()) : "";
            String measured = dim != null ? org.apache.commons.lang3.StringUtils.defaultString(dim.getMeasuredValue()) : "";

            Cell c0 = getOrCreateCell(r, startCol);
            c0.setCellValue(dimName);
            c0.setCellStyle(style);

            Cell c1 = getOrCreateCell(r, startCol+1);
            c1.setCellValue(req);
            c1.setCellStyle(style);

            Cell c2 = getOrCreateCell(r, startCol+2);
            c2.setCellValue(measured);
            c2.setCellStyle(style);

            // 注意：结论列现在使用报告的 finalJudgement
            Cell c3 = getOrCreateCell(r, startCol+3);
            c3.setCellValue("");
            c3.setCellStyle(style);
        }
    }

    private Row getOrCreateRow(Sheet sheet, int rowIdx) {
        Row row = sheet.getRow(rowIdx);
        if (row == null) {
            row = sheet.createRow(rowIdx);
            row.setHeightInPoints(20);
        }
        return row;
    }

    private Cell getOrCreateCell(Row row, int colIdx) {
        Cell cell = row.getCell(colIdx);
        if (cell == null) {
            cell = row.createCell(colIdx);
        }
        return cell;
    }

    private byte[] readFileBytesSafe(String path) {
        if (org.apache.commons.lang3.StringUtils.isBlank(path)) return null;
        File f = new File(path);
        if (!f.exists()) return null;
        try (FileInputStream fis = new FileInputStream(f); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            byte[] buf = new byte[8192];
            int len;
            while ((len = fis.read(buf)) != -1) {
                baos.write(buf, 0, len);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            return null;
        }
    }


    public Long openByTask(Long taskId, boolean initAppearance) {
        if (taskId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "任务ID不能为空");
        }
        com.yupi.springbootinit.model.entity.WorkflowTask task = workflowTaskMapper.selectById(taskId);
        if (task == null) {
            var qw = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.yupi.springbootinit.model.entity.WorkflowTask>()
                    .eq(com.yupi.springbootinit.model.entity.WorkflowTask::getBizType, "PROCESS_BATCH_STEP")
                    .eq(com.yupi.springbootinit.model.entity.WorkflowTask::getBizId, taskId)
                    .eq(com.yupi.springbootinit.model.entity.WorkflowTask::getTaskType, "QUALITY_INSPECTION")
                    .eq(com.yupi.springbootinit.model.entity.WorkflowTask::getIsDelete, 0)
                    .orderByDesc(com.yupi.springbootinit.model.entity.WorkflowTask::getCreateTime)
                    .last("LIMIT 1");
            task = workflowTaskMapper.selectOne(qw);
        }
        if (task == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "任务不存在或类型错误");
        }
        if ("GENERATE_INSPECTION_REPORT".equals(task.getTaskType()) && "PROCESS_SHEET".equals(task.getBizType())) {
            Long processSheetId = task.getBizId();
            
            // 注：订单状态已在所有批次完成时更新为INSPECTING，此处不需要重复更新
            
            QaInspectionReport exist = this.lambdaQuery()
                    .eq(QaInspectionReport::getProcessSheetId, processSheetId)
                    .eq(QaInspectionReport::getIsDelete, 0)
                    .last("limit 1").one();
            if (exist != null) {
                return exist.getId();
            }
            Date now = new Date();
            QaInspectionReport report = new QaInspectionReport();
            report.setReportDate(now);
            report.setProcessSheetId(processSheetId);
            report.setTaskId(task.getId());
            ProcessSheet sheet = processSheetService.getById(processSheetId);
            if (sheet != null) {
                report.setProductName(sheet.getProductName());
                report.setSpecModel(sheet.getSpecification());
                report.setQuantity(sheet.getQuantity());
            }
            report.setFinalJudgement("PENDING");
            report.setDimensionConclusion("PENDING");
            report.setAppearanceConclusion("PENDING");
            String dateKey = new SimpleDateFormat("yyyyMMdd").format(now);
            QaInspectionReportSeq seq = qaInspectionReportSeqService.getById(dateKey);
            if (seq == null) { seq = new QaInspectionReportSeq(); seq.setDateKey(dateKey); seq.setNextVal(1); qaInspectionReportSeqService.save(seq);} else { seq.setNextVal(seq.getNextVal()+1); qaInspectionReportSeqService.updateById(seq);}            report.setReportNo(dateKey + String.format("%02d", seq.getNextVal()));
            this.save(report);
            for (int i=1;i<=10;i++) { QaInspectionReportDim dim = new QaInspectionReportDim(); dim.setReportId(report.getId()); dim.setItemNo("FAI"+i); dim.setRequirement(""); dim.setMeasuredValue(""); dim.setOrderNo(i); qaInspectionReportDimService.save(dim);}            return report.getId();
        }
        if (!"QUALITY_INSPECTION".equals(task.getTaskType())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "任务类型错误");
        }
        Long stepId = task.getBizId();
        com.yupi.springbootinit.model.entity.ProcessBatchStep step = processBatchStepMapper.selectById(stepId);
        ThrowUtils.throwIf(step == null || step.getIsDeleted() == 1, ErrorCode.NOT_FOUND_ERROR, "工序不存在");
        com.yupi.springbootinit.model.entity.ProcessBatch batch = processBatchMapper.selectById(step.getBatchId());
        ThrowUtils.throwIf(batch == null || batch.getIsDeleted() == 1, ErrorCode.NOT_FOUND_ERROR, "批次不存在");
        QaInspectionReport existByBatch = this.lambdaQuery()
                .eq(QaInspectionReport::getBatchId, batch.getId())
                .eq(QaInspectionReport::getIsDelete, 0)
                .last("limit 1").one();
        if (existByBatch != null) { return existByBatch.getId(); }
        Date now = new Date();
        QaInspectionReport report = new QaInspectionReport();
        report.setReportDate(now);
        report.setProcessSheetId(batch.getProcessSheetId());
        report.setBatchId(batch.getId());
        report.setTaskId(task.getId());
        report.setProductName(batch.getProductName());
        report.setQuantity(batch.getQuantity());
        report.setLotNo(batch.getBatchCode());
        if (batch.getProcessSheetId() != null) {
            ProcessSheet sheet = processSheetService.getById(batch.getProcessSheetId());
            if (sheet != null) { report.setSpecModel(sheet.getSpecification()); }
        }
        report.setFinalJudgement("PENDING");
        report.setDimensionConclusion("PENDING");
        report.setAppearanceConclusion("PENDING");
        String dateKey = new SimpleDateFormat("yyyyMMdd").format(now);
        QaInspectionReportSeq seq = qaInspectionReportSeqService.getById(dateKey);
        if (seq == null) { seq = new QaInspectionReportSeq(); seq.setDateKey(dateKey); seq.setNextVal(1); qaInspectionReportSeqService.save(seq);} else { seq.setNextVal(seq.getNextVal()+1); qaInspectionReportSeqService.updateById(seq);}        report.setReportNo(dateKey + String.format("%02d", seq.getNextVal()));
        this.save(report);
        for (int i=1;i<=10;i++) { QaInspectionReportDim dim = new QaInspectionReportDim(); dim.setReportId(report.getId()); dim.setItemNo("FAI"+i); dim.setRequirement(""); dim.setMeasuredValue(""); dim.setOrderNo(i); qaInspectionReportDimService.save(dim);}        return report.getId();
    }



    private byte[] readClasspathBytes(String classpathLocation) {
        try (InputStream is = new ClassPathResource(classpathLocation).getInputStream();
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            if (is == null) return null;
            byte[] buf = new byte[8192];
            int len;
            while ((len = is.read(buf)) != -1) {
                baos.write(buf, 0, len);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            return null;
        }
    }
}